package com.qixiaobao.direct.invoice.service.impl;

import com.qixiaobao.common.core.domain.model.LoginUser;
import com.qixiaobao.common.exception.UtilException;
import com.qixiaobao.common.utils.SecurityUtils;
import com.qixiaobao.common.utils.StringUtils;
import com.qixiaobao.common.utils.easyExcel.EasyExcelUtil;
import com.qixiaobao.direct.invoice.domain.dto.DirectInvoiceDTO;
import com.qixiaobao.direct.invoice.domain.vo.DirectInvoiceChargeVO;
import com.qixiaobao.direct.invoice.domain.vo.DirectInvoiceVO;
import com.qixiaobao.direct.invoice.domain.vo.DirectWaitInvoiceVO;
import com.qixiaobao.direct.invoice.mapper.DirectInvoiceMapper;
import com.qixiaobao.direct.invoice.service.IDirectInvoiceService;
import com.qixiaobao.nondirect.invoice.domain.domain.Invoice;
import com.qixiaobao.nondirect.invoice.domain.domain.InvoiceBill;
import com.qixiaobao.nondirect.invoice.mapper.InvoiceBillMapper;
import com.qixiaobao.nondirect.invoice.mapper.InvoiceMapper;
import com.qixiaobao.system.domain.Dict;
import com.qixiaobao.system.domain.SlaveUser;
import com.qixiaobao.system.mapper.DictMapper;
import com.qixiaobao.system.mapper.SlaveUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @Description 直投发票管理 - 业务层实现
 * @Author yangxm
 * @Date 2025/7/2 15:41
 */
@Slf4j
@Service
public class DirectInvoiceServiceImpl implements IDirectInvoiceService {

    @Autowired
    private DirectInvoiceMapper directInvoiceMapper;
    @Autowired
    private DictMapper dictMapper;
    @Autowired
    private SlaveUserMapper slaveUserMapper;
    @Autowired
    private InvoiceBillMapper invoiceBillMapper;
    @Autowired
    private InvoiceMapper invoiceMapper;

    /**
     * @Description 查询待开票列表
     * @Author yangxm
     * @Date 2025/7/2 15:46
     * @param directInvoiceDTO
     * @return java.util.List<com.qixiaobao.direct.domain.vo.DirectWaitInvoiceVO>
     */
    @Override
    public List<DirectWaitInvoiceVO> selectWaitInvoiceList(DirectInvoiceDTO directInvoiceDTO) {
        log.info("查询直投发票管理-待开票列表，参数：{}", directInvoiceDTO);
        List<DirectWaitInvoiceVO> list = directInvoiceMapper.selectWaitInvoiceList(directInvoiceDTO);
        if (StringUtils.isNotEmpty(list)){
            //字典
            Map<String, String> invoiceTypeMap = dictMapper.selectDictListByType("invoice_type").stream().
                    collect(Collectors.toMap(Dict::getK, Dict::getVal));
            //客服信息
            Map<Long, String> usernameMap = slaveUserMapper.selectUsernameList().stream()
                    .collect(Collectors.toMap(SlaveUser::getId, SlaveUser::getUsername));

            DirectWaitInvoiceVO item;
            for (int i = 0; i < list.size(); i++) {
                item = list.get(i);
                item.setInvoiceTypeVal(invoiceTypeMap.get(item.getInvoiceType()));
                item.setServiceName(usernameMap.getOrDefault(item.getServiceId(), ""));
                item.setSettlePersonNum(item.getAddNum() - item.getMinusNum());
            }
        }
        return list;
    }

    /**
     * @Description 查询待开票 - 开票金额合计
     * @Author yangxm
     * @Date 2025/7/3 9:45
     * @param directInvoiceDTO
     * @return java.math.BigDecimal
     */
    @Override
    public BigDecimal selectWaitInvoiceTotal(DirectInvoiceDTO directInvoiceDTO) {
        return directInvoiceMapper.selectWaitInvoiceTotal(directInvoiceDTO);
    }

    /**
     * @Description 查询开票中、已开票列表
     * @Author yangxm
     * @Date 2025/7/3 9:45
     * @param directInvoiceDTO
     * @return java.util.List<com.qixiaobao.direct.domain.vo.DirectInvoicingVO>
     */
    @Override
    public List<DirectInvoiceVO> selectInvoiceList(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        if (directInvoiceDTO.getInsureProofStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureProofStatusVal = directInvoiceDTO.getInsureProofStatus() == 0 ? "开票中" : directInvoiceDTO.getInsureProofStatus() == 1 ? "已开票" : "";
        if (StringUtils.isBlank(insureProofStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("查询直投发票管理-{}列表，参数：{}", insureProofStatusVal, directInvoiceDTO);
        List<DirectInvoiceVO> list = directInvoiceMapper.selectInvoiceList(directInvoiceDTO);
        log.info("查询直投发票管理-{}列表sql，耗时：{}ms", insureProofStatusVal, System.currentTimeMillis() - begin);
        if (StringUtils.isNotEmpty(list)){
            //字典
            Map<String, String> invoiceTypeMap = dictMapper.selectDictListByType("invoice_type").stream().
                    collect(Collectors.toMap(Dict::getK, Dict::getVal));

            //客服信息
            Map<Long, String> usernameMap = slaveUserMapper.selectUsernameList().stream()
                    .collect(Collectors.toMap(SlaveUser::getId, SlaveUser::getUsername));

            DirectInvoiceVO item;
            for (int i = 0; i < list.size(); i++) {
                item = list.get(i);
                item.setInvoiceTypeVal(invoiceTypeMap.get(item.getInvoiceType()));
                item.setServiceName(usernameMap.getOrDefault(item.getServiceId(), ""));
            }
        }
        log.info("查询直投发票管理-{}列表完成，总耗时：{}ms", insureProofStatusVal, System.currentTimeMillis() - begin);
        return list;
    }

    /**
     * @Description 查询开票中、已开票 - 开票金额合计
     * @Author yangxm
     * @Date 2025/7/3 11:53
     * @param directInvoiceDTO
     * @return java.math.BigDecimal
     */
    @Override
    public BigDecimal selectInvoiceTotal(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        if (directInvoiceDTO.getInsureProofStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureProofStatusVal = directInvoiceDTO.getInsureProofStatus() == 0 ? "开票中" : directInvoiceDTO.getInsureProofStatus() == 1 ? "已开票" : "";
        if (StringUtils.isBlank(insureProofStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("查询直投发票管理-{}开票金额合计，参数：{}", insureProofStatusVal, directInvoiceDTO);
        BigDecimal amount = directInvoiceMapper.selectInvoiceTotal(directInvoiceDTO);
        log.info("查询直投发票管理-{}开票金额合计完成，总耗时：{}ms", insureProofStatusVal, System.currentTimeMillis() - begin);
        return amount;
    }

    /**
     * @Description 开票中、已开票 导出
     * @Author yangxm
     * @Date 2025/7/3 13:07
     * @param directInvoiceDTO
     * @param response
     */
    @Override
    public void export(DirectInvoiceDTO directInvoiceDTO, HttpServletResponse response) {
        long begin = System.currentTimeMillis();
        if (directInvoiceDTO.getInsureProofStatus() == null){
            throw new UtilException("参数：开票状态不能为空！");
        }
        String insureProofStatusVal = directInvoiceDTO.getInsureProofStatus() == 0 ? "开票中" : directInvoiceDTO.getInsureProofStatus() == 1 ? "已开票" : "";
        if (StringUtils.isBlank(insureProofStatusVal)){
            throw new UtilException("参数：开票状态有误！");
        }
        log.info("导出直投发票管理-{}列表，参数：{}", insureProofStatusVal, directInvoiceDTO);
        String fileName = "直投发票管理-" + insureProofStatusVal + "列表";
        List<String> arrayHeaders = new ArrayList<>();
        arrayHeaders.add("序号");
        if(directInvoiceDTO.getInsureProofStatus() == 0){
            arrayHeaders.add("税号");
        }
        arrayHeaders.add("发票编号");
        if(directInvoiceDTO.getInsureProofStatus() == 0){
            arrayHeaders.add("公司注册地址");
            arrayHeaders.add("公司注册电话");
            arrayHeaders.add("开户银行");
            arrayHeaders.add("银行账号");
        }
        arrayHeaders.add("供应商全称");
        arrayHeaders.add("供应商简称");
        arrayHeaders.add("付款单位");
        arrayHeaders.add("开票金额");
        arrayHeaders.add("发票类型");
        arrayHeaders.add("客服");
        arrayHeaders.add("开票时间");
        arrayHeaders.add("操作时间");
        arrayHeaders.add("备注");
        //动态表头
        List<List<String>> headList = new ArrayList<>();
        String headStr;
        List<String> headArray;
        for (int i = 0; i < arrayHeaders.size(); i++) {
            headStr = arrayHeaders.get(i);
            headArray = new ArrayList<>();
            headArray.add(headStr);
            headList.add(headArray);
        }
        List<DirectInvoiceVO> list = selectInvoiceList(directInvoiceDTO);
        //动态表头的数据
        List<List<Object>> datalist = new ArrayList<>();
        List<Object> obj = null;
        DirectInvoiceVO  item;
        for (int j = 0; j < list.size(); j++) {
            item = list.get(j);
            obj = new ArrayList<>();
            obj.add(j + 1);

            if(directInvoiceDTO.getInsureProofStatus() == 0){
                obj.add(item.getTaxNum());
            }
            obj.add(item.getInvoiceNo());
            if(directInvoiceDTO.getInsureProofStatus() == 0){
                obj.add(item.getCompanyAddress());
                obj.add(item.getCompanyPhone());
                obj.add(item.getBankName());
                obj.add(item.getBankNum());
            }
            obj.add(item.getSupplyName());
            obj.add(item.getSupplyShortName());
            obj.add(item.getCustomerName());
            obj.add(item.getInsureFee());
            obj.add(item.getInvoiceTypeVal());
            obj.add(item.getServiceName());
            obj.add(Optional.ofNullable(item.getCreateTime()).map(x-> DateFormatUtils.format(x, "yyyy/MM/dd HH:mm:ss")).orElse(""));
            obj.add(Optional.ofNullable(item.getUpdateTime()).map(x-> DateFormatUtils.format(x, "yyyy/MM/dd HH:mm:ss")).orElse(""));
            obj.add(item.getSupplyRemark());
            datalist.add(obj);
        }
        try {
            EasyExcelUtil.writeExcel(response, datalist, headList, fileName, fileName);
        } catch (IOException e) {
            log.error(" {}导出异常：", fileName, e);
            throw new RuntimeException("导出失败：" + e.getMessage());
        }
        log.info("导出直投发票管理-{}列表完成，总耗时：{}", insureProofStatusVal, System.currentTimeMillis() - begin);
    }

    /**
     * @Description 开票中 - 修改供应商备注
     * @Author yangxm
     * @Date 2025/7/3 13:18
     * @param directInvoiceDTO
     * @return int
     */
    @Override
    public int updateSupplyRemark(DirectInvoiceDTO directInvoiceDTO) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        if (loginUser == null){
            throw new UtilException("获取登录信息失败，请重新登录！");
        }
        directInvoiceDTO.setSupplyRemarkOperator(loginUser.getUsername());
        return directInvoiceMapper.updateSupplyRemark(directInvoiceDTO);
    }

    /**
     * @Description 开票中 - 上传发票文件
     * @Author yangxm
     * @Date 2025/7/3 13:37
     * @param directInvoiceDTO
     * @return int
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int uploadInvoiceFile(DirectInvoiceDTO directInvoiceDTO) {
        long begin = System.currentTimeMillis();
        log.info("直投发票管理-开票中，上传发票文件，参数：{}", directInvoiceDTO);
        //开票账单信息
        InvoiceBill invoiceBill = invoiceBillMapper.selectInvoiceIdById(directInvoiceDTO.getInvoiceBillId());
        if (invoiceBill == null){
            throw new UtilException("未找到对应发票信息");
        }
        invoiceBill.setInsureFeeProof(directInvoiceDTO.getInsureFeeProof());
        invoiceBill.setInsureProofStatus(1);
        invoiceBillMapper.updateInsureFeeProof(invoiceBill);
        //开票信息
        Invoice invoice = invoiceMapper.selectInvoiceById(invoiceBill.getInvoiceId());
        if (invoice == null){
            throw new UtilException("未找到对应发票信息");
        }
        invoice.setInsureFeeProof(directInvoiceDTO.getInsureFeeProof());
        invoice.setInsureProofStatus(1);
        int row = invoiceMapper.updateInsureFeeProof(invoice);
        log.info("直投发票管理-开票中，上传发票文件完成，总耗时：{}", System.currentTimeMillis() - begin);
        return row;
    }

    /**
     * @Description 开票中、已开票 - 费用详情
     * @Author yangxm
     * @Date 2025/7/3 14:53
     * @param invoiceId
     * @return java.util.List<com.qixiaobao.directinvoice.domain.vo.DirectInvoiceChargeVO>
     */
    @Override
    public List<DirectInvoiceChargeVO> selectInvoiceChargeList(Long invoiceId) {
        long begin = System.currentTimeMillis();
        log.info("直投发票管理-开票中、已开票-费用详情，参数：{}", invoiceId);
        List<DirectInvoiceChargeVO> list = directInvoiceMapper.selectInvoiceChargeList(invoiceId);
        return null;
    }
}
